package com.ititer.web.abs;

import static br.com.caelum.vraptor.view.Results.json;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import br.com.caelum.vraptor.Result;
import br.com.caelum.vraptor.Validator;
import br.com.caelum.vraptor.core.Localization;
import br.com.caelum.vraptor.validator.I18nMessage;
import br.com.caelum.vraptor.validator.Message;

import com.ititer.enums.PublicKeys;
import com.ititer.helper.ValidationHelper;
import com.ititer.model.Account;
import com.ititer.service.AccountService;
import com.ititer.service.CodeDictionaryService;
import com.ititer.web.Bean;
import com.ititer.web.Controller;
import com.ititer.web.controller.Error;
import com.ititer.web.controller.Login;

public abstract class AbstractController implements Controller {
	final Logger logger = LoggerFactory.getLogger(AbstractController.class);

	@Autowired
	protected Result controllerResult = null;
	@Autowired
	protected Validator validator = null;
	@Autowired
	protected final HttpServletRequest request = null;
	@Autowired
	protected final HttpServletResponse response = null;
	@Autowired
	protected final ValidationHelper validationHelper = null;
	@Autowired
	private final Localization localization = null;

	@Autowired
	protected CodeDictionaryService codeDictionarySvc;

	@Autowired
	protected AccountService accountSvc;

	protected void setPageTitle(String title) {
		controllerResult.include(PublicKeys.PageTitle.getValue(), title);
	}

	protected Validator validate(final Bean bean) {
		List<Message> messages = validationHelper.validate(bean);
		validator.addAll(messages);
		return validator;
	}

	protected void setErrorMessage(String messageKey, Object... params) {
		I18nMessage message = new I18nMessage(PublicKeys.Error.getValue(), messageKey, params);
		message.setBundle(localization.getBundle());
		controllerResult.include(PublicKeys.Errors.getValue(), new I18nMessage[] { message });
	}

	protected String getIp() {
		return request.getRemoteAddr();
	}

	protected String getReferer() {
		return request.getHeader(PublicKeys.Referer.getValue());
	}

	/**
	 * Add data into a collection and set this collection into request attribute.
	 * @param key
	 * @param data
	 */
	@SuppressWarnings("unchecked")
	protected void addData(String key, Object data) {
		Collection<Object> coll = null;
		Object existData = controllerResult.included().get(key);
		if (existData == null || !(existData instanceof Collection)) {
			coll = new ArrayList<Object>();
			if (existData != null) {
				coll.add(existData);
			}
		} else {
			coll = (Collection<Object>) existData;
		}
		coll.add(data);
		controllerResult.include(key, coll);
	}

	/**
	 * Put data into request attribute.
	 * @param keys
	 * @param data
	 */
	protected void putData(String keys, Object data) {
		controllerResult.include(keys, data);
	}

	@SuppressWarnings("unchecked")
	protected <T> T pullData(String key, Class<T> clazz) {
		return (T) controllerResult.included().get(key);
	}

	protected Object pullData(String key) {
		return controllerResult.included().get(key);
	}

	protected void saveSession(Account account) {
		HttpSession session = request.getSession(true);
		session.setMaxInactiveInterval(3600);
		session.setAttribute(PublicKeys.CurrentUser.getValue(), account);
	}

	protected Account getSession() {
		HttpSession session = request.getSession();
		Object account = session.getAttribute(PublicKeys.CurrentUser.getValue());
		if (account == null) {
			return null;
		}
		return (Account) account;
	}

	protected void removeSession() {
		HttpSession session = request.getSession();
		session.removeAttribute(PublicKeys.CurrentUser.getValue());
		session.invalidate();
	}

	protected boolean isLogedIn() {
		Account account = getSession();
		if (account == null) {
			return false;
		}
		return true;
	}

	protected void loginCheck() {
		if (!isLogedIn()) {
			toLoginForm();
		}
	}

	protected void toLoginForm() {
		controllerResult.redirectTo(Login.class).form();
	}

	protected void toError() {
		controllerResult.redirectTo(Error.class).info();
	}

	protected void outputJson(String jsonObjectName, Object data) {
		controllerResult.use(json()).from(data, jsonObjectName).serialize();
	}
}
